package com.zl.tby.core.base.util;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;

/**
 * @author changpeng
 * @since 2025/11/12 8:07
 */
public class NativeImageCompressor {
    /**
     * 原生 API 按比例等比压缩
     */
    public static void nativeScaleCompress(String sourcePath, String targetPath, float scale, float quality) throws IOException {
        File sourceFile = new File(sourcePath);
        BufferedImage sourceImage = ImageIO.read(sourceFile);

        // 1. 计算等比新宽高
        int newWidth = (int) (sourceImage.getWidth() * scale);
        int newHeight = (int) (sourceImage.getHeight() * scale);

        // 2. 绘制缩放后的图片（抗锯齿，提升清晰度）
        BufferedImage scaledImage = createScaledImage(sourceImage, newWidth, newHeight);

        // 3. 输出图片（支持 JPEG/PNG）
        writeImage(scaledImage, targetPath, quality);
    }

    /**
     * 原生 API 按目标宽高等比压缩（不超过 maxWidth/maxHeight）
     */
    public static void nativeFixedSizeCompress(String sourcePath, String targetPath, int maxWidth, int maxHeight, float quality) throws IOException {
        File sourceFile = new File(sourcePath);
        BufferedImage sourceImage = ImageIO.read(sourceFile);

        int originalWidth = sourceImage.getWidth();
        int originalHeight = sourceImage.getHeight();

        // 1. 计算等比缩放比例（若原图小于目标宽高，比例为 1.0f，不缩放）
        float scale = 1.0f;
        if (originalWidth > maxWidth || originalHeight > maxHeight) {
            float widthScale = (float) maxWidth / originalWidth;
            float heightScale = (float) maxHeight / originalHeight;
            scale = Math.min(widthScale, heightScale); // 取最小值，确保不超过目标宽高
        }

        // 2. 计算新宽高
        int newWidth = (int) (originalWidth * scale);
        int newHeight = (int) (originalHeight * scale);

        // 3. 绘制缩放图片
        BufferedImage scaledImage = createScaledImage(sourceImage, newWidth, newHeight);

        // 4. 输出图片
        writeImage(scaledImage, targetPath, quality);
    }

    // 工具方法：绘制缩放后的图片（抗锯齿优化）
    private static BufferedImage createScaledImage(BufferedImage source, int newWidth, int newHeight) {
        BufferedImage scaledImage = new BufferedImage(newWidth, newHeight,
                source.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = scaledImage.createGraphics();

        // 抗锯齿、平滑缩放优化
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);

        g2d.drawImage(source, 0, 0, newWidth, newHeight, null);
        g2d.dispose();
        return scaledImage;
    }

    // 工具方法：将 BufferedImage 写入文件（支持质量压缩）
    private static void writeImage(BufferedImage image, String targetPath, float quality) throws IOException {
        String format = getFileSuffix(targetPath);
        FileOutputStream fos = new FileOutputStream(targetPath);

        // 获取图片写入器
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
        if (!writers.hasNext()) {
            throw new IOException("不支持的图片格式：" + format);
        }
        ImageWriter writer = writers.next();
        ImageWriteParam param = writer.getDefaultWriteParam();

        // JPEG 格式支持质量压缩，PNG 无损不支持
        if (format.equalsIgnoreCase("jpg") || format.equalsIgnoreCase("jpeg")) {
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality);
        }

        // 输出图片
        writer.setOutput(ImageIO.createImageOutputStream(fos));
        writer.write(null, new IIOImage(image, null, null), param);

        // 关闭资源
        writer.dispose();
        fos.close();
    }

    // 工具方法：获取文件后缀
    private static String getFileSuffix(String filePath) {
        return filePath.substring(filePath.lastIndexOf(".") + 1).toLowerCase();
    }

    // 测试
    public static void main(String[] args) throws IOException {
        nativeFixedSizeCompress("D:/aaa/3395.jpg", "D:/aaa/3395650x300.jpg", 650, 300, 0.75f);
        nativeFixedSizeCompress("D:/aaa/3395.jpg", "D:/aaa/3395132x103.jpg", 132, 103, 0.75f);

//        String uploadResponse = HttpUtil.uploadFile("http://172.20.1.6:12007/file/upload/img", "D:/aaa/2403132x103.jpg");
//        System.out.println(uploadResponse);
    }
}
